<script>

var tabs = {};
var blocked = [];
var whitelisted = [];

var whiteListTo = [];
var whiteListFrom = [];


// storage stuff

function isStorageSupported()
{
  try
  {
    return 'localStorage' in window && window['localStorage'] !== null;
  }
  catch (e)
  {
    return false;
  }
}

function setData(name, x)
{
  if(isStorageSupported())
  {
    localStorage[name] = x;
  }
}

function getData(name)
{
  if(isStorageSupported())
  {
    var x = localStorage[name]; 
    return x; 
  }
  return null;
}

function restoreWhiteListTo()
{
  var s = getData("whiteListTo");
  if(s != undefined && s.length > 0)
  {
    log('WhiteListTo read:' + s);
    whiteListTo = s.split(",");
  }
}

function restoreWhiteListFrom()
{
  var s = getData("whiteListFrom");
  if(s != undefined && s.length > 0)
  {
    log('WhiteListFrom read:' + s);
    whiteListFrom = s.split(",");
  }
}

function mergeWhiteListTo(add)
{
  for(i = 0; i < add.length; i++)
  {
    if(whiteListTo.indexOf(add[i]) == -1)
    {
      whiteListTo.push(add[i]);
    }
  }
  var s = whiteListTo.join();
  log('WhiteListTo saved:' + s);
  setData("whiteListTo", s);
}

function mergeWhiteListFrom(add)
{
  for(i = 0; i < add.length; i++)
  {
    if(whiteListFrom.indexOf(add[i]) == -1)
    {
      whiteListFrom.push(add[i]);
    }
  }
  var s = whiteListFrom.join();
  log('WhiteListFrom saved:' + s);
  setData("whiteListFrom", s);
}

function replaceWhiteListTo(add)
{
  whiteListTo = [];
  whiteListTo = add.slice(0);
  var s = whiteListTo.join();
  log('WhiteListTo saved:' + s);
  setData("whiteListTo", s);
}

function replaceWhiteListFrom(add)
{
  whiteListFrom = [];
  whiteListFrom = add.slice(0);
  var s = whiteListFrom.join();
  log('WhiteListFrom saved:' + s);
  setData("whiteListFrom", s);
}

// URL stuff

function URL(url)
{
  url = url || "";
  this.parse(url);
}

URL.prototype =
{
  href: "",
  protocol: "",
  host: "",
  hostname: "",
  port: "",
  pathname: "",
  search: "",
  hash: "",
    
  parse: function(url)
  {
    url = url || this.href;
    var pattern = "^(([^:/\\?#]+):)?(//(([^:/\\?#]*)(?::([^/\\?#]*))?))?([^\\?#]*)(\\?([^#]*))?(#(.*))?$";
    var rx = new RegExp(pattern); 
    var parts = rx.exec(url);
    
    this.href = parts[0] || "";
    this.protocol = parts[2] || "";
    this.host = parts[4] || "";
    this.hostname = parts[5] || "";
    this.port = parts[6] || "";
    this.pathname = parts[7] || "/";
    this.search = parts[8] || "";
    this.hash = parts[10] || "";
    
    this.update();
  },
    
  update: function()
  {
    this.host = this.hostname + (("" + this.port) ? ":" + this.port : "");
    this.href = this.protocol + '//' + this.host + this.pathname + this.search + this.hash;
  },
    
  assign: function(url)
  {
    this.parse(url);
  },
  
  similar: function(that)
  {
    if(that instanceof Object && typeof that.hostname == 'string')
    {
      var domains1 = this.hostname.split('.').reverse();
      var domains2 = that.hostname.split('.').reverse();
      for(i = 0; i < 2; i++) // domains1.length
      {
        // if(domains1[i] == 'www' && i == domains1.length - 1) break;
        if(domains1[i] != domains2[i]) return false;
      }
      return true;
    }
    return false;
  }
}

function interceptRequest(request)
{
  if(request && request.url)
  {
    if(!tabs[request.tabId]) return {cancel: false};
    
    var urlCurrent = new URL(tabs[request.tabId]);
    var urlNext = new URL(request.url);
    
    if(request.type == "main_frame") // new page/site is loading in main window
    {
      if(blocked[request.tabId]) delete blocked[request.tabId];
      if(whitelisted[request.tabId]) delete whitelisted[request.tabId];
      
      // icon will be automatically reset to default on every new page
      
      chrome.browserAction.setBadgeText({text:'', tabId:request.tabId});
      
      if(whiteListFrom.indexOf(urlCurrent.host) != -1)
      {
        //log('skip host:' + urlCurrent.host);
        whitelisted[request.tabId] = true;
        chrome.browserAction.setIcon({path:"domaincage_icon_green_32.png", tabId:request.tabId});
        return {cancel: false};
      }
      
      return {cancel: false};
    }
    
    // can be chrome: or chrome-extension:, ftp:, etc
    if(urlCurrent.protocol != 'http' && urlCurrent.protocol != 'https') return {cancel: false}; 
    if(urlNext.protocol != 'http' && urlNext.protocol != 'https') return {cancel: false};
    
    if(whiteListTo.indexOf(urlNext.host) != -1)
    {
      //log('skip whitelisted:' + urlNext.host);
      return {cancel: false};
    } 

    if(whiteListFrom.indexOf(urlCurrent.host) != -1)
    {
      return {cancel: false};
    }

    var filtered = whiteListTo.filter(endsWith('.' + urlNext.host));
    if(filtered.length > 0)
    {
      return {cancel: false};
    }

    if(urlCurrent.similar(urlNext))
    {
      return {cancel: false};
    }    
    
    if(urlCurrent.host != urlNext.host)
    {
      console.log('blocked ' + request.url + ' from ' + tabs[request.tabId] + ' ' + request.type);
      if(blocked[request.tabId] == undefined)
      {
        blocked[request.tabId] = {"origin": tabs[request.tabId], "urls":[], "domains":[]};
      }
      blocked[request.tabId].urls.push(request.url);
      
      var domain = urlNext.host;//.replace(/^www\./g, "");
      
      if(blocked[request.tabId].domains.indexOf(domain) == -1)
      {
        blocked[request.tabId].domains.push(domain);
      }
      chrome.browserAction.setIcon({path:"domaincage_icon_red_32.png", tabId:request.tabId});
      
      chrome.browserAction.setBadgeText({text:blocked[request.tabId].domains.length.toString(), tabId:request.tabId});
      if(request.type == "sub_frame" || request.type == "other")
      {
        return {redirectUrl: chrome.extension.getURL("empty.html")};
      }
      else
      {
        return {cancel: true};
      }
    } 
  }
  return {cancel: false};
}

function endsWith(str)
{
  return function(suffix)
  {
    return str.indexOf(suffix, str.length - suffix.length) !== -1;
  }
}

function getTabHost(id)
{
  if(blocked[id])
  {
    var u = new URL(blocked[id].origin);
    return u.host;
  }
  return null;
}

function tabCreated(tab)
{
  if(tab.url != undefined && tab.url != null)
  {
    console.log('created:' + tab.id + ' ' + tab.url);
    tabs[tab.id] = tab.url;
  }
}

function tabUpdated(tabId, changeInfo, tab)
{
  if(tab.url)
  {
    console.log('updated:' + tabId + ' ' + tab.url + ' ' + blocked[tabId] + ' ' + whitelisted[tabId]);
    tabs[tabId] = tab.url;
    
    // this event does not fire all the time
    if(blocked[tabId] != undefined)
    {
      chrome.browserAction.setIcon({path:"domaincage_icon_red_32.png", tabId:tabId});
    }
    else
    if(whitelisted[tabId] != undefined)
    {
      chrome.browserAction.setIcon({path:"domaincage_icon_green_32.png", tabId:tabId});
    }
  }
}

function log(s)
{
  console.log(s);
}

restoreWhiteListTo();
restoreWhiteListFrom();

chrome.tabs.onCreated.addListener(tabCreated);
chrome.tabs.onUpdated.addListener(tabUpdated);
if(chrome.experimental.webRequest == undefined)
{
  chrome.webRequest.onBeforeRequest.addListener(interceptRequest, {urls: ["*://*/*"]}, ['blocking']);
}
else
{
  chrome.experimental.webRequest.onBeforeRequest.addListener(interceptRequest, null, ['blocking']);
}

</script>
